package com.wxy.service.serviceimpl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wxy.config.jwtConfig;
import com.wxy.dao.UserBookDao;
import com.wxy.dao.UserDao;
import com.wxy.dao.UserImgDao;
import com.wxy.domain.RedisUser;
import com.wxy.domain.User;
import com.wxy.domain.UserBookNum;
import com.wxy.domain.UserImg;
import com.wxy.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;

import java.util.concurrent.TimeUnit;

/**
 * @author 47868
 */
@Service("LoginService")
public class LoginServiceImpl implements LoginService {
    private final UserDao userDao;
    private final StringRedisTemplate stringRedisTemplate;
    private final UserBookDao userBookDao;
    private final UserImgDao userImgDao;
    public static final String ERROR_MESSAGE ="没有该用户";

    @Autowired
    public LoginServiceImpl(UserDao userDao,
                            StringRedisTemplate stringRedisTemplate,
                            UserBookDao userBookDao,
                            UserImgDao userImgDao) {
        this.userDao = userDao;
        this.stringRedisTemplate = stringRedisTemplate;
        this.userBookDao = userBookDao;
        this.userImgDao = userImgDao;
    }

    /**建立 redis 缓存，降低数据库压力
     *
     * @param username 根据传入的用户名判断登录成功与否
     * @return 用户实体或者错误信息
     */
    public Object getUser(String username) {
        // 查询 redis
        String userString = stringRedisTemplate.opsForValue().get("user:" + username);
        // 有数据返回
        if (StrUtil.isNotBlank(userString)) {
            return JSONUtil.toBean(userString, RedisUser.class);
        }
        if (userString != null) {
            return "没有该用户";
        }
        // 无数据查询数据库
        User user = userDao.selectOne(new QueryWrapper<User>().eq("username", username));
        if (user == null) {
            stringRedisTemplate.opsForValue().set("user:" + username, " ", 2, TimeUnit.MINUTES);
            return "没有该用户";
        }
        RedisUser redisUser = new RedisUser(user,false);
        stringRedisTemplate.opsForValue().set("user:" + username, JSONUtil.toJsonStr(redisUser), 30, TimeUnit.MINUTES);
        return redisUser;
    }

    /**用户登录
     *
     * @param username 账号
     * @param password 密码
     * @param model model实体
     * @return 跳转界面
     */
    @Override
    public String login(String username, String password, Model model) {
        Object object = getUser(username);
        if (ERROR_MESSAGE.equals(object)) {
            model.addAttribute("message", "账号或密码错误,请重试...");
            return "login";
        }
        if (object instanceof RedisUser user) {
            if(user.isLogin()){
                model.addAttribute("message","该账号已经在线...");
                return "login";
            }
            if (!user.getUser().getPassword().equals(password)) {
                model.addAttribute("message", "账号或密码错误,请重试...");
                return "login";
            }
            user.setLogin(true);
            stringRedisTemplate.opsForValue().set("user:"+user.getUser().getUsername(),JSONUtil.toJsonStr(user),30, TimeUnit.MINUTES);
            return jwtConfig.getToken(user.getUser().getId());
        }
        model.addAttribute("message", "账号或密码错误,请重试...");
        return "login";
    }

    /**
     *用户注册功能
     * @param username 账号
     * @param password 密码
     * @param email 邮箱
     * @param model model实体
     * @return 跳转界面
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String register(String username, String password, String email, Model model) {
        Object object = getUser(username);
        if (ERROR_MESSAGE.equals(object)) {
            int id = userDao.findMaxId() + 1;
            long cardId = System.currentTimeMillis();
            User newUser = new User(id, cardId, username, password, email);
            UserBookNum userBookNum = new UserBookNum(cardId,10);
            RedisUser redisUser = new RedisUser(newUser,true);
            userDao.insert(newUser);
            userBookDao.insert(userBookNum);
            UserImg userImg = new UserImg(cardId,"default.jpg");
            userImgDao.insert(userImg);
            stringRedisTemplate.opsForValue().set("user:" + username, JSONUtil.toJsonStr(redisUser), 30, TimeUnit.MINUTES);
            return jwtConfig.getToken(newUser.getId());
        }
        model.addAttribute("message", "用户名已存在...");
        return "login";
    }
}